home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Enigma Amiga Life 112
/
EnigmaAmiga112CD.iso
/
dalla rivista
/
news
/
orbit
/
source
/
client.c
< prev
next >
Wrap
C/C++ Source or Header
|
2000-05-01
|
21KB
|
1,113 lines
/*
Amiga port by Oliver Gantert
27.04.2000 - fixed a lot of compiler warnings
*/
/*
ORBIT, a freeware space combat simulator
Copyright (C) 1999 Steve Belczyk <steve1@genesis.nred.ma.us>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "orbit.h"
#ifndef AMIGA
#ifndef WIN32
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#endif /* WIN32 */
#include <fcntl.h>
#endif /* AMIGA */
#include <errno.h>
#include <limits.h>
#include <stdarg.h>
/*
* All sorts of stuff a client needs
*/
int FindClient()
/*
* Find an unused client
*/
{
int c;
for (c=0; c<NCLIENTS; c++)
{
if (!client[c].active)
{
client[c].active = 1;
return c;
}
}
/* Ran out */
return (-1);
}
void DoClient()
/*
* Handle ORBIT client duties
*/
{
#ifndef AMIGA
char buf[1024];
int r, e;
/* Bump timers */
clientme.timer.server += deltaT;
clientme.timer.pos += deltaT;
/* If server has been idle too long, goodbye */
if (clientme.timer.server > MAXSERVERIDLE)
{
Mprint ("Server is not responding");
Log ("DoClient: Dropping idle server");
#ifndef WIN32
close (clientme.socket);
#else
closesocket (clientme.socket);
#endif
am_client = 0;
return;
}
/* Time to report position? */
if (clientme.timer.pos >= CLIENTPOSINTERVAL)
{
ReportPosition();
clientme.timer.pos = 0.0;
}
/* Try to read from the server */
r = recv (clientme.socket, buf, 1024, 0);
/* If recv returns zero the other side has gone away */
if (r == 0)
{
Mprint ("Dropped by server");
Log ("DoClient: Dropped by server");
#ifndef WIN32
close (clientme.socket);
#else
closesocket (clientme.socket);
#endif
am_client = 0;
InitNetwork();
InitTargets();
return;
}
/* If we get an error it better be EWOULDBLOCK */
#ifndef WIN32
if (r < 0)
{
if (errno == EWOULDBLOCK)
{
/* All is well, no data from server */
return;
}
else
{
/* Uh oh */
Log ("DoClient: recv() error: %d", errno);
return;
}
}
#else
if (r == SOCKET_ERROR)
{
e = WSAGetLastError();
if (e == WSAEWOULDBLOCK)
{
/* All is well, no data from server */
return;
}
else
{
/* Uh oh */
Log ("DoClient: recv() error: %d", e);
return;
}
}
#endif
/* We really have data from the server! */
clientme.timer.server = 0.0;
/* Handle the data */
buf[r] = 0;
recv_bytes += r;
/* Log ("DoClient: Server data: %s", buf); */
ServerData (buf, r);
#endif /* AMIGA */
}
void ServerData (char *buf, int n)
/*
* Separate incoming data into packets
*/
{
int i;
#ifndef BINARYPACKETS
int ch, j;
#endif
#ifdef BINARYPACKETS
for (i=0; i<n; i++) ServerByte (buf[i]);
#else
j = clientme.ptr;
for (i=0; i<n; i++)
{
ch = clientme.pkt[j] = buf[i];
j = (j + 1) % 1024;
/* Got a packet? */
if (ch == 0)
{
ServerPacket (clientme.pkt);
j = 0;
}
}
clientme.ptr = j;
#endif
}
void ServerByte (char c)
/*
* Process one byte from server
*/
{
switch (clientme.state)
{
case NETSTATE_MAGIC:
if (c == NET_MAGIC)
{
clientme.state = NETSTATE_SIZE;
}
break;
case NETSTATE_SIZE:
clientme.remain = 0xff & c;
clientme.ptr = 0;
clientme.state = NETSTATE_PACKET;
if (clientme.remain == 0) clientme.state = NETSTATE_MAGIC;
break;
case NETSTATE_PACKET:
clientme.pkt[clientme.ptr++] = c;
clientme.remain--;
if (clientme.remain == 0)
{
clientme.pkt[clientme.ptr] = 0;
ServerPacket (clientme.pkt);
clientme.state = NETSTATE_MAGIC;
}
break;
default:
Log ("ServerByte: PANIC! No such state: %d", clientme.state);
break;
}
}
void ServerPacket (char *pkt)
/*
* Handle a packet from the server
*/
{
char cmd[128];
/* If high bit of first byte is set, this is a binary packet */
if (0x80 & pkt[0])
{
ServerBinaryPacket (pkt);
return;
}
/* Sanity check on packet */
if ( (strlen(pkt) == 0) ||
(pkt[0] == ' ') ||
(pkt[0] == '\r') ||
(pkt[0] == '\n') ||
(pkt[0] == '\t') )
{
Log ("ServerPacket: Insane packet: %s", pkt);
return;
}
/* Extract command part */
sscanf (pkt, "%s", cmd);
/* Dispatch */
if (!strcasecmp (cmd, "poss"))
{
ServerPositionShort (pkt);
return;
}
else if (!strcasecmp (cmd, "posl"))
{
ServerPositionLong (pkt);
return;
}
else if (!strcasecmp (cmd, "ping"))
{
ServerPing (pkt);
return;
}
else if (!strcasecmp (cmd, "fire"))
{
ServerFire (pkt);
return;
}
else if (!strcasecmp (cmd, "mhit"))
{
ServerMHit (pkt);
return;
}
else if (!strcasecmp (cmd, "mdie"))
{
ServerMDie (pkt);
return;
}
else if (!strcasecmp (cmd, "mesg"))
{
ServerMessage (pkt);
return;
}
else if (!strcasecmp (cmd, "name"))
{
ServerName (pkt);
return;
}
else if (!strcasecmp (cmd, "vcnt"))
{
ServerVacant (pkt);
return;
}
else if (!strcasecmp (cmd, "modl"))
{
ServerModel (pkt);
return;
}
else if (!strcasecmp (cmd, "flag"))
{
ServerFlag (pkt);
return;
}
else if (!strcasecmp (cmd, "crat"))
{
ServerCrater (pkt);
return;
}
else if (!strcasecmp (cmd, "cmsg"))
{
ServerCMSG (pkt);
return;
}
else if (!strcasecmp (cmd, "helo"))
{
ServerHelo (pkt);
return;
}
else if (!strcasecmp (cmd, "gbye"))
{
ServerGbye (pkt);
return;
}
else if (!strcasecmp (cmd, "welc"))
{
ServerWelcome (pkt);
return;
}
else if (!strcasecmp (cmd, "plan"))
{
ServerPlanet (pkt);
return;
}
else if (!strcasecmp (cmd, "rpln"))
{
ServerResetPlanets (pkt);
return;
}
else
{
Log ("ServerPacket: Unrecongized command: %s", cmd);
return;
}
}
void ServerPing (char *pkt)
/*
* Handle ping packet from server
*/
{
/* Just send it right back */
SendASCIIPacket (clientme.socket, pkt);
}
void ServerBinaryPing (char *pkt)
/*
* Handle binary ping packet
*/
{
double t;
/* Decode */
DecodeBinaryPacket (pkt, "F", &t);
/* Echo */
SendBinaryPacket (clientme.socket, "cF", PKT_PING, t);
}
void ServerMessage (char *pkt)
/*
* Text message from server
*/
{
/* Print it to the screen */
if ( (pkt[4] != 0) && (pkt[5] != 0) )
{
Mprint (&pkt[5]);
}
}
void ServerWelcome (char *pkt)
/*
* Server says hello and gives us our client number
*/
{
int i, t;
/* Extract client number */
if (1 != sscanf (pkt, "%*s %d", &i)) return;
/* Set up our client */
Log ("ServerWelcome: I am client %d", i);
clientme.client = i;
/* Set up client and target */
client[i].active = 1;
client[i].is_me = 1;
client[i].frags = 0;
t = client[i].target = InitClientTarget();
strcpy (target[t].name, player.name);
target[t].hidden = target[t].invisible = 1;
}
void ReportPosition()
/*
* Report my position
*/
{
#ifdef BINARYPACKETS
int c;
#else
char cmd[5];
#endif
/* Not if we're dead */
if ( (state == STATE_DEAD1) || (state == STATE_DEAD2) ) return;
/* Urgent? */
if (clientme.urgent)
{
#ifdef BINARYPACKETS
c = PKT_POSU;
#else
strcpy (cmd, "POSU");
#endif
clientme.urgent = 0;
}
else
{
#ifdef BINARYPACKETS
c = PKT_POSN;
#else
strcpy (cmd, "POSN");
#endif
}
#ifdef BINARYPACKETS
SendBinaryPacket (clientme.socket, "cVVvvffffff", c,
player.pos, player.vel, player.view, player.up,
player.move_up, player.move_down,
player.move_right, player.move_left,
player.move_pitchright, player.move_pitchleft);
#else
SendASCIIPacket (clientme.socket,
"POSN %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf\n",
player.pos[0], player.pos[1], player.pos[2],
player.vel[0], player.vel[1], player.vel[2],
player.view[0], player.view[1], player.view[2],
player.up[0], player.up[1], player.up[2],
player.move_up, player.move_down,
player.move_right, player.move_left,
player.move_pitchright, player.move_pitchleft);
#endif
}
void ServerPositionShort (char *pkt)
/*
* The server is sending a client's short position report
*/
{
int c;
double pos[3], vel[3];
/* Parse packet */
if (7 != sscanf (pkt, "%*s %d %lf %lf %lf %lf %lf %lf", &c,
&player.pos[0], &player.pos[1], &player.pos[2],
&player.vel[0], &player.vel[1], &player.vel[2]))
{
Log ("ServerPositionShort: Malformed POSS packet: %s", pkt);
return;
}
PositionShort (c, pos, vel);
}
void PositionShort (int c, double *pos, double *vel)
/*
* Process short position report
*/
{
int t;
/* Sanity */
if ((c<0) || (c>=NCLIENTS)) return;
/* Mark client active */
client[c].active = 1;
/* Is it for me? */
if (client[c].is_me)
{
Vset (player.pos, pos);
Vset (player.vel, vel);
}
else
{
/* Not for me, see if we have target for this client */
if ((-1) == (t = client[c].target))
{
t = client[c].target = InitClientTarget();
}
/* Make target unhidden */
target[t].hidden = 0;
/* Set position */
Vset (target[t].pos, pos);
Vset (target[t].vel, vel);
}
}
void ServerPositionLong (char *pkt)
/*
* The server is sending a client's long position report
*/
{
int c;
double pos[3], vel[3], view[3], up[3], move_up, move_down, move_left;
double move_right, move_pitchright, move_pitchleft;
/* Parse packet */
if (19 != sscanf (pkt, "%*s %d %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf",
&c,
&pos[0], &pos[1], &pos[2], &vel[0], &vel[1], &vel[2],
&view[0], &view[1], &view[2], &up[0], &up[1], &up[2],
&move_up, &move_down, &move_right, &move_left,
&move_pitchright, &move_pitchleft))
{
Log ("ServerPositionLong: Malformed POSL packet: %s", pkt);
return;
}
PositionLong (c, pos, vel, view, up, move_up, move_down, move_right,
move_left, move_pitchright, move_pitchleft);
}
void PositionLong ( int c, double *pos, double *vel, double *view, double *up,
double move_up, double move_down, double move_right, double move_left,
double move_pitchright, double move_pitchleft )
/*
* Process a long position report
*/
{
int t;
/* Sanity */
if ((c<0) || (c>=NCLIENTS)) return;
/* Mark client active */
client[c].active = 1;
/* Is it for me? */
if (client[c].is_me)
{
Vset (player.pos, pos);
Vset (player.vel, vel);
Vset (player.view, view);
Vset (player.up, up);
player.move_up = move_up;
player.move_down = move_down;
player.move_left = move_left;
player.move_right = move_right;
player.move_pitchright = move_pitchright;
player.move_pitchleft = move_pitchleft;
Crossp (player.right, player.up, player.view);
}
else
{
/* Not for me, see if we have target for this client */
if ((-1) == (t = client[c].target))
{
t = client[c].target = InitClientTarget();
}
/* Make target unhidden */
target[t].hidden = 0;
/* Set position */
Vset (target[t].pos, pos);
Vset (target[t].vel, vel);
Vset (target[t].view, view);
Vset (target[t].up, up);
target[t].move_up = move_up;
target[t].move_down = move_down;
target[t].move_left = move_left;
target[t].move_right = move_right;
target[t].move_pitchright = move_pitchright;
target[t].move_pitchleft = move_pitchleft;
Normalize (target[t].up);
Normalize (target[t].view);
Crossp (target[t].right, target[t].up, target[t].view);
}
}
void ServerMHit (char *pkt)
/*
* We were hit by a missile
*/
{
double yield;
/* Parse packet */
if (1 != sscanf (pkt, "%*s %lf", &yield))
{
Log ("ServerMHit: Malformed MHIT packet: %s", pkt);
return;
}
/* Flash screen red */
palette_flash = 2;
/* Damage shields */
player.shields -= yield;
if (player.shields < 0.0) player.shields = 0.0;
}
void ServerMDie (char *pkt)
/*
* Someone was killed. Hope it wasn't me!
*/
{
int ckiller, cvictim;
double v[3], d;
/* Parse packet */
if (2 != sscanf (pkt, "%*s %d %d", &cvictim, &ckiller))
{
Log ("ServerMDie: Malformed MDIE packet: %s", pkt);
return;
}
/* Adjust frags */
client[ckiller].frags++;
/* Tell me about it */
Cprint ("%s was killed by %s",
target[client[cvictim].target].name,
target[client[ckiller].target].name);
/* Was it me? */
if (cvictim == clientme.client)
{
Cprint ("YOU were killed!");
NetPlayerDies();
}
else
{
/* Make target hidden */
target[client[cvictim].target].hidden = 1;
/* Make a boom if close enough */
Vsub (v, player.pos, target[client[cvictim].target].pos);
d = Mag2 (v);
if (d <= TARG_MAXRANGE2) Boom (target[client[cvictim].target].pos, 1.0);
}
CheckLock();
}
void ServerCrater (char *pkt)
/*
* Someone hit a planet. Hope it wasn't me!
*/
{
int c, p;
double v[3], d;
/* Parse packet */
if (2 != sscanf (pkt, "%*s %d %d", &c, &p))
{
Log ("ServerMDie: Malformed CRAT packet: %s", pkt);
return;
}
/* Adjust frags */
client[c].frags--;
/* Tell me about it */
Cprint ("%s cratered on %s",
target[client[c].target].name, planet[p].name);
/* Was it me? */
if (c == clientme.client)
{
NetPlayerDies();
}
else
{
/* Make target hidden */
target[client[c].target].hidden = 1;
/* Make a boom if close enough */
Vsub (v, player.pos, target[client[c].target].pos);
d = Mag2 (v);
if (d <= TARG_MAXRANGE2) Boom (target[client[c].target].pos, 1.0);
}
CheckLock();
}
void ServerFire (char *pkt)
/*
* Someone nearby has fired a missile
*/
{
int c, t, w;
/* Parse packet */
if (2 != sscanf (pkt, "%*s %d %d", &c, &w))
{
Log ("ServerFire: Malformed FIRE packet: %s", pkt);
return;
}
/* Get target for this client */
t = client[c].target;
/* Fire the missile! */
FireMissile (target[t].pos, target[t].vel, target[t].view,
0, w, t);
}
void ServerPlanet (char *pkt)
/*
* Server sends the position of a planet
*/
{
int p;
double theta;
/* Parse packet */
if (2 != sscanf (pkt, "%*s %d %lf", &p, &theta))
{
Log ("ServerPlanet: Malformed PLAN packet: %s", pkt);
return;
}
if ((p >= 0) && (p < NPLANETS)) planet[p].theta = theta;
}
void ServerBinaryPlanet (char *pkt)
/*
* Server sends the position of a planet in binary
*/
{
int p;
double theta;
/* Parse packet */
DecodeBinaryPacket (pkt, "cF", &p, &theta);
/* Set planet angle */
if ((p >= 0) && (p < NPLANETS)) planet[p].theta = theta;
}
void ServerResetPlanets (char *pkt)
/*
* Server done sending planet positions
*/
{
PositionPlanets();
}
void ServerName (char *pkt)
/*
* Server sends us the name of an active client
*/
{
int c, t, f;
char buf[256];
/* Parse packet */
if (3 != sscanf (pkt, "%*s %d %s %d", &c, buf, &f))
{
Log ("ServerName: Malformed NAME packet: %s", pkt);
return;
}
/* Sanity check */
if ((c<0) || (c>=NCLIENTS)) return;
/* Log ("ServerName: NAME %d %s %d", c, buf, f); */
/* Don't bother if it's us */
if (c == clientme.client)
{
client[c].frags = f;
return;
}
/* Show client is active */
client[c].active = 1;
/* Set up a target if we didn't know about this one */
if ((-1) == (t = client[c].target))
{
t = InitClientTarget();
client[c].target = t;
}
/* Set name and frags */
strcpy (target[t].name, buf);
client[c].frags = f;
}
void ServerHelo (char *pkt)
/*
* A new client has joined the game
*/
{
int c, t;
char buf[256];
/* Parse packet */
if (2 != sscanf (pkt, "%*s %d %s", &c, buf))
{
Log ("ServerName: Malformed HELO packet: %s", pkt);
return;
}
/* Sanity check */
if ((c<0) || (c>=NCLIENTS)) return;
/* Tell us */
Cprint ("%s is here", buf);
Log ("ServerHelo: HELO %d %s", c, buf);
/* Don't bother if it's us */
if (c == clientme.client) return;
/* Set up a target if we didn't know about this one */
if ((-1) == (t = client[c].target))
{
t = InitClientTarget();
client[c].target = t;
}
/* Set name */
strcpy (target[t].name, buf);
}
void ServerVacant (char *pkt)
/*
* Server tells us about an unused client slot
*/
{
int c;
/* Parse packet */
if (1 != sscanf (pkt, "%*s %d", &c))
{
Log ("ServerVacant: Malformed VCNT packet: %s", pkt);
return;
}
if ((c<=0) || (c>=NCLIENTS)) return;
Log ("ServerVacant: VCNT %d", c);
/* Don't bother if it's us (this should never happen!) */
if (c == clientme.client)
{
Log ("ServerVacant: PANIC! Server says I am vacant!");
return;
}
/* Destroy any associated target */
if ((-1) != client[c].target) DestroyTarget (client[c].target);
client[c].active = 0;
client[c].target = (-1);
}
void ServerGbye (char *pkt)
/*
* Someone has left the game
*/
{
int c;
char buf[256];
/* Parse packet */
if (2 != sscanf (pkt, "%*s %d %s", &c, buf))
{
Log ("ServerVacant: Malformed GBYE packet: %s", pkt);
return;
}
if ((c<=0) || (c>=NCLIENTS)) return;
Log ("ServerGbye: GBYE %d", c);
/* Don't bother if it's us (this should never happen!) */
if (c == clientme.client)
{
Log ("ServerGbye: PANIC! Server says I am gone!");
return;
}
/* Tell us */
Cprint ("%s is gone", buf);
/* Destroy any associated target */
if ((-1) != client[c].target) DestroyTarget (client[c].target);
client[c].active = 0;
client[c].target = (-1);
}
void ServerCMSG (char *pkt)
/*
* Server has a console message for us
*/
{
/* Sanity */
if ( (pkt[4] == 0) || (pkt[5] == 0) ) return;
/* Show it */
Cprint ("%s", &pkt[5]);
/* Give the sound */
if (sound) PlayAudio (SOUND_COMM);
}
void ServerFlag (char *pkt)
/*
* Game flags from server
*/
{
int f;
/* Parse packet */
if (1 != sscanf (pkt, "%*s %d", &f))
{
Log ("ServerFlag: Malformed FLAG packet: %s", pkt);
return;
}
/* Set flags */
gravity = (f & FLAG_GRAVITY) ? 1 : 0;
player.flightmodel = (f & FLAG_FLIGHTMODEL) ? FLIGHT_ARCADE : FLIGHT_NEWTONIAN;
fullstop = (f & FLAG_FULLSTOP) ? 1 : 0;
realdistances = (f & FLAG_REALDISTANCES) ? 1 : 0;
orbit = (f & FLAG_ORBIT) ? 1 : 0;
}
void DoConnect ()
/*
* Sparky has finished typing the server address
*/
{
BecomeClient (text.buf);
}
void ServerModel (char *pkt)
/*
* Set client model
*/
{
char buf[128];
int m, c;
/* Parse packet */
if (2 != sscanf (pkt, "%*s %d %s", &c, buf))
{
Log ("ServerModel: Malformed MODL packet: %s", pkt);
return;
}
/* Sanity */
if ( (c < 0) || (c >= NCLIENTS) || (!client[c].active) || (client[c].is_me) ) return;
/* Try to load model */
m = LoadModel (buf);
/* Success? */
if (m != (-1))
{
target[client[c].target].model = m;
target[client[c].target].list = model[m].list;
}
else
{
Log ("ServerModel: LoadModel (%s) failed", buf);
/* Use default model */
m = LoadModel ("light2.tri");
target[client[c].target].model = m;
target[client[c].target].list = model[m].list;
}
}
void ServerBinaryPacket (unsigned char *pkt)
/*
* Handle binary packet from server
*/
{
/* Dispatch */
switch (pkt[0])
{
case PKT_POSS:
BinaryPositionShort (&pkt[1]);
break;
case PKT_POSL:
BinaryPositionLong (&pkt[1]);
break;
case PKT_PLAN:
ServerBinaryPlanet (&pkt[1]);
break;
case PKT_VCNT:
ServerBinaryVacant (&pkt[1]);
break;
case PKT_PING:
ServerBinaryPing (&pkt[1]);
break;
default:
Log ("ServerBinaryPacket: Unrecognized packet type: 0x%x",
pkt[0]);
break;
}
}
void BinaryPositionShort (unsigned char *pkt)
/*
* Binary short position report
*/
{
int c;
double pos[3], vel[3];
DecodeBinaryPacket (pkt, "cVV", &c, pos, vel);
PositionShort (c, pos, vel);
}
void BinaryPositionLong (unsigned char *pkt)
/*
* Binary long position report
*/
{
int c;
double pos[3], vel[3], view[3], up[3];
double move_up, move_down;
double move_right, move_left, move_pitchright, move_pitchleft;
DecodeBinaryPacket (pkt, "cVVvvffffff", &c, pos, vel, view, up,
&move_up, &move_down, &move_right, &move_left,
&move_pitchright, &move_pitchleft);
PositionLong (c, pos, vel, view, up,
move_up, move_down, move_right, move_left,
move_pitchright, move_pitchleft);
}
void ServerBinaryVacant (char *pkt)
/*
* Server tells us which clients are in use
*/
{
int c;
unsigned int w, bit, i1, i2;
/* Parse packet */
DecodeBinaryPacket (pkt, "cc", &i1, &i2);
w = i1 + 256*i2;
/* See which bits are set */
bit = 1;
for (c=0; c<NCLIENTS; c++)
{
if (!(w & bit))
{
/* Don't bother if it's us (this should never happen!) */
if (c == clientme.client)
{
Log ("ServerVacant: PANIC! Server says I am vacant!");
return;
}
/* Destroy any associated target */
if ((-1) != client[c].target) DestroyTarget (client[c].target);
client[c].active = 0;
client[c].target = (-1);
}
bit = bit * 2;
}
}